package coordinator

import (
	"adai.design/homemaster/container/accessory"
	"adai.design/homemaster/container/characteristic"
	"adai.design/homemaster/container/characteristic/to"
	"adai.design/homemaster/log"
	"encoding/hex"
	"fmt"
	"github.com/gorilla/websocket"
	"strings"
)

// Extended Colour Light
type zigbeeLightColorTemperature struct {
	*ZigbeeDescriptor
	acc *accessory.LightColorTemperature
}

func (z *zigbeeLightColorTemperature) update(data []byte) error {
	return nil
}

func (z *zigbeeLightColorTemperature) onSwitchUpdate(endpoint uint8, value uint8) {
	//log.Printf("(%04x) chan(%d) set(%d)\n", z.macAddr, z.netAddr, channel, value)
	data := make([]byte, 6)
	data[0] = 0x02
	netAddr, _ := hex.DecodeString(z.NetAddr)
	copy(data[1:], netAddr)
	data[3] = 0x01
	data[4] = endpoint
	data[5] = value
	msg := &Message{MsgT: SerialLinkMsgTypeOnOffNoEffects, Data: data}
	sdata, err := msg.Encode()
	if err != nil {
		log.Fatal(err)
	}
	client.task <- sdata
}

func (z *zigbeeLightColorTemperature) onLevelUpdate(endpoint uint8, value uint8) {
	log.Debug("level value: %d", value)
	str := "02 " + z.NetAddr + " 01" + fmt.Sprintf("%02x", endpoint) + "00 " + fmt.Sprintf("%02x", int(value)*255/100) + " 0000"
	str = strings.Replace(str, " ", "", -1)
	data, _ := hex.DecodeString(str)
	msg := &Message{MsgT: SerialLinkMsgTypeMoveToLevel, Data: data}
	sdata, err := msg.Encode()
	if err != nil {
		log.Fatal(err)
	}
	client.task <- sdata
}

func (z *zigbeeLightColorTemperature) onColorTemperatureUpdate(endpoint uint8, value int64) {
	t := int(1000000 / value)
	str := "02 " + z.NetAddr + " 01" + fmt.Sprintf("%02x", endpoint) + fmt.Sprintf("%04x", t) + "0000"
	str = strings.Replace(str, " ", "", -1)
	data, _ := hex.DecodeString(str)
	msg := &Message{MsgT: SerialLinkMsgTypeMoveToColourTemperature, Data: data}
	sdata, err := msg.Encode()
	if err != nil {
		log.Fatal(err)
	}
	client.task <- sdata
}

func newTemperatureColorLightLight(zigbee *ZigbeeDescriptor) *zigbeeLightColorTemperature {
	var descriptor *EndPointDescriptor
	for _, v := range zigbee.Descriptors {
		if v.DeviceId == ZigbeeDeviceZLLColourTemperatureLight || v.DeviceId == ZigbeeDeviceZHAColourTemperatureLight {
			descriptor = v
			break
		}
	}
	if descriptor == nil {
		return nil
	}

	light := &zigbeeLightColorTemperature{
		ZigbeeDescriptor: zigbee,
		acc:              accessory.NewLightColorTemperature(zigbee.MacAddr),
	}

	light.acc.Light.SetId(int(descriptor.Endpoint))
	light.acc.Light.On.OnValueUpdateFromConn(func(conn *websocket.Conn, c *characteristic.Characteristic, newValue, oldValue interface{}) {
		if newValue == characteristic.SwitchStateOn {
			light.onSwitchUpdate(uint8(light.acc.Light.GetId()), 1)
			light.acc.Light.On.UpdateValue(characteristic.SwitchStateOn)
		} else {
			light.onSwitchUpdate(uint8(light.acc.Light.GetId()), 0)
			light.acc.Light.On.UpdateValue(characteristic.SwitchStateOff)
		}
	})

	light.acc.Light.Level.OnValueUpdateFromConn(func(conn *websocket.Conn, c *characteristic.Characteristic, newValue, oldValue interface{}) {
		log.Debug("light level value (%v)", newValue)
		value := to.Int64(newValue)
		light.onLevelUpdate(uint8(light.acc.Light.GetId()), uint8(value))
		light.acc.Light.Level.UpdateValue(value)
	})

	light.acc.Light.Temperature.OnValueUpdateFromConn(func(conn *websocket.Conn, c *characteristic.Characteristic, newValue, oldValue interface{}) {
		log.Debug("light color value (%v)", newValue)
		light.onColorTemperatureUpdate(uint8(light.acc.Light.GetId()), to.Int64(newValue))
		light.acc.Light.Temperature.UpdateValue(newValue)
	})
	return light
}
